﻿using Microsoft.AspNetCore.SignalR;
using System.Runtime.CompilerServices;
using System.Threading.Channels;

namespace WebApi.Hubs;

/// <summary>
/// SignalR Hub for streaming data
/// </summary>
public class UseStreamingInHub : Hub
{
    /// <summary>
    /// Asynchronous counter that streams integers to the client
    /// 使用 IAsyncEnumerable 实现异步流
    /// </summary>
    /// <param name="count"></param>
    /// <param name="delay"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async IAsyncEnumerable<int> Counter(int count, int delay, [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        for (int i = 0; i < count; i++)
        {
            // Check the cancellation token regularly to see if the operation has been cancelled
            cancellationToken.ThrowIfCancellationRequested(); // Check for cancellation
            Console.WriteLine($"Counter:{i + 1}");
            //await Task.Delay(1000); // Simulate some delay
            //yield return $"Message {i + 1} from server at {DateTime.Now}";
            yield return i + 1; // Return the current count

            await Task.Delay(delay, cancellationToken); // Simulate some delay
        }

    }

    /// <summary>
    /// Counter channel that streams integers to the client using ChannelReader
    /// 使用 ChannelReader 实现异步流
    /// </summary>
    /// <param name="count"></param>
    /// <param name="delay"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public ChannelReader<int> CounterChannel(int count, int delay, CancellationToken cancellationToken)
    {
        var channel = Channel.CreateUnbounded<int>();
        _ = Task.Run(async () =>
        {
            for (int i = 0; i < count; i++)
            {
                cancellationToken.ThrowIfCancellationRequested(); // Check for cancellation
                await channel.Writer.WriteAsync(i + 1, cancellationToken); // Write to the channel
                Console.WriteLine($"CounterChannel:{i + 1}");
                await Task.Delay(delay, cancellationToken); // Simulate some delay
            }
            channel.Writer.Complete(); // Mark the channel as complete
        }, cancellationToken);
        return channel.Reader; // Return the reader to read from the channel
    }

    /// <summary>
    /// Upload a stream of strings to the server
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    public async Task UploadStream(ChannelReader<string> stream)
    {
        // 添加异常处理，确保在读取流时捕获异常
        try
        {
            while (await stream.WaitToReadAsync())
            {
                while (stream.TryRead(out var item))
                {
                    // do something with the stream item
                    Console.WriteLine(item);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

    /// <summary>
    /// Upload a stream of strings to the server using IAsyncEnumerable
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    public async Task UploadStream2(IAsyncEnumerable<string> stream)
    {
        try
        {
            await foreach (var item in stream)
            {
                // do something with the stream item
                Console.WriteLine(item);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }
}
